package game.Russian;

import java.util.function.Function;

public class Matrix {

	private int[][] matr;
	private final int MIN_ROW=2;
	private final int MIN_COLUMN=2;
	private int row=MIN_ROW;
	private int column=MIN_COLUMN;

	//矩阵默认有效值
	public static final int GrapVal=1;
	//矩阵默认值初始值
	public static final int DefVal=0;

	//通过构造方法初始化矩阵，矩阵最低要求2行2列
	public Matrix (int row,int column) {
		if(row>MIN_ROW && column>MIN_COLUMN) {
			matr=new int[row][column];
			this.row=row;
			this.column=column;
		}else {
			matr=new int[MIN_ROW][MIN_COLUMN];
		}
	}

	protected void setValue(Matrix value) {
		this.matr=value.get();
		this.column=value.getColumn();
		this.row=value.getRow();
	}

	//计算矩阵中的每一个元素
	public void setforEach(Function<Integer,Integer> fun) {
		for(int i=0;i<row;i++) {
			for(int j=0;j<column;j++) {
				matr[i][j]=fun.apply(matr[i][j]);
			}
		}
	}
	//设置矩阵中第row行的数据
	public void setRowValue(Function<Integer,Integer> fun,int rowIndex) {
		if(rowIndex<0 || rowIndex>=this.row) return;

		for(int i=0;i<column;i++) {
			matr[rowIndex][i]=fun.apply(matr[rowIndex][i]);
		}
	}
	//设置矩阵中第column列的数据
	public void setColumnValue(Function<Integer,Integer> fun,int columnIndex) {
		if(columnIndex<0 || columnIndex>=this.column) return;

		for(int i=0;i<this.column;i++) {
			matr[i][columnIndex]=fun.apply(matr[i][columnIndex]);
		}
	}

	public int[][] get(){
		return this.matr;
	}

	public boolean isValueByRow(int row) {
		if(row>=0 && row<this.row) {
			int[] rowValue=this.matr[row];
			for(int temp:rowValue) {
				if(temp==Matrix.GrapVal) return true;
			}
		}

		return false;
	}

	public boolean isValueByColumn(int column) {
		if(column>=0 && column<this.column) {
			for(int i=0;i<this.row;i++) {
				if(this.matr[i][column]==Matrix.GrapVal)
					return true;
			}
		}

		return false;
	}

	//克隆方法
	public Matrix clone() {
		Matrix newMatr=new Matrix(this.row,this.column);
		for(int i=0;i<row;i++) {
			for(int j=0;j<column;j++) {
				newMatr.matr[i][j]=this.matr[i][j];
			}
		}
		return newMatr;
	}

	/**
	 * 矩阵相加：以当前矩阵为基础，与另一个矩阵相加。可以指定相加的偏移量。
	 * @param added 加数
	 * @param rowIndex 行偏移量
	 * @param columnIndex 列偏移量
	 * @return 相加后的矩阵
	 */
	public Matrix add(Matrix addMatr,int rowIndex,int columnIndex) {
		if(addMatr==null) return this;
		Matrix newMatr=this.clone();

		int[][] added=addMatr.get();//相加的目标矩阵
		for(int i=0;i<added.length;i++) {
			for(int j=0;j<added[i].length;j++) {
				int addRow=i+rowIndex;//计算基础矩阵相加的行位置
				int addColumn=j+columnIndex;//计算基础矩阵相加的列位置
				//如果相加的位置越界，不进行计算
				if(addRow>=0 && addRow<row
						&& addColumn>=0
						&& addColumn<column){

					newMatr.matr[addRow][addColumn]=matr[addRow][addColumn]
							+added[i][j];
				}
			}
		}

		return newMatr;
	}

	public Matrix add(Matrix addMatr){
		return this.add(addMatr, 0, 0);
	}

	// 当前矩阵向右旋转90度
	public void rightRotate(){
		if(row!=column) return;
		int half=row%2==0?row/2:row/2+1;

		for(int i=0;i<half;i++) {
			for(int j=i;j<row-i-1;j++) {
				//旋转
				int temp=matr[i][j];
				matr[i][j]=matr[row-j-1][i];//4->1
				matr[row-j-1][i]=matr[row-i-1][row-j-1];//3->4
				matr[row-i-1][row-j-1]=matr[j][row-i-1];//2->3
				matr[j][row-i-1]=temp;//1->2
			}
		}
	}
	/**
	 *
	 * @param angel 旋转角度 取，90的整数倍，做旋转次数。
	 * @return
	 */
	public void rightRotate(int angle) {
		if(angle<0) {
			leftRotate(angle*-1);
		}else {
			angle/=90;
			int size=1;
			if(angle%3==0) size=3;
			if(angle%2==0) size=2;
			while(size-->0) {
				rightRotate();
			}
		}
	}
	//同rightRotate，方向相反
	public void leftRotate(int angle) {
		if(angle<0) {
			rightRotate(angle*-1);
		}else {
			angle/=90;
			int size=3;
			if(angle%3==0) size=1;
			if(angle%2==0) size=2;
			while(size-->0) {
				rightRotate();
			}
		}
	}

	public int getRow() {
		return this.row;
	}

	public int getColumn() {
		return this.column;
	}
}
